// ZFunction.h: interface for the ZFunction class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_ZFUNCTION_H__4D84F5B7_572F_11D1_93C2_006097737B41__INCLUDED_)
#define AFX_ZFUNCTION_H__4D84F5B7_572F_11D1_93C2_006097737B41__INCLUDED_

//#if _MSC_VER >= 1000
//#pragma once
//#endif // _MSC_VER >= 1000

#include "Function.h"
#include <cmath>
#include <iostream>


#include "Molecule.h"
#include "Diffractor.h"
#include "Likelihood.h"

#include "Time.h" // to check time of cal a set of calculated intensities
                 // relative to additional overhead of cal derivatives
                 // for the purpose of first publication of HMC

using namespace std;

class ZFunction : public Function  
{
public:
	ZFunction(int i_NInput, char *ZMatrixFile, char *DiffractorFile);
	virtual ~ZFunction();

  double Value(double *Input);
  double Value(vector<double> &Input);

  void   BuildDerivative(double *Input, double *Derivative);
  double distanceFromGlobalMinimum(double *solution);

	Molecule   *MyMolecule;

	// printing out solution
	void print_sol(double *Input, double ChiSq, char name[], int NAccept, int NTotal)
	{

		//MyMolecule->PrintCartesians(Input);
		//MyMolecule->PrintFractional(Input, ChiSq, name, NAccept, NTotal);
    MyMolecule->PrintCIF(Input, ChiSq, name);
	}

  void print_sol(double *Input, double ChiSq, ofstream& append, string cifLabel = "default")
	{
    MyMolecule->PrintCIF(Input, ChiSq, append, cifLabel);
	}

	// crap programming
	void createRandomSol(double *TestInput)
	{
		MyMolecule->createRandomSol(TestInput);

    // These are the cartesian coords for famotidine which yields
    // a successful solution
    /*TestInput[1] = 1.6998355624659254;
    TestInput[2] = 2.9615837127066351;
    TestInput[3] = 11.023239195680652;
    TestInput[4] = 2.5796456221520865;
    TestInput[5] = 1.1271147203342038;
    TestInput[6] = 1.4986139295760259;
    TestInput[7] = 2.4959217923069961;
    TestInput[8] = 2.4654745311212820;
    TestInput[9] = 1.5430791263171433;
    TestInput[10] = 0.77477669291000917;
    TestInput[11] = 1.3987084298201857;
    TestInput[12] = 1.5900247484941603;
    TestInput[13] = 2.7820933180761354;*/

    // These are the cartesian coords for capsaicin which yields
    // a successful solution
    /*TestInput[1] = 1.8466889349158093;
    TestInput[2] = 0.45929749921722235;
    TestInput[3] = 5.8084928399112208;
    TestInput[4] = 1.1949634868992958;
    TestInput[5] = 2.2761854819881226;
    TestInput[6] = 1.0552331983286194;
    TestInput[7] = 0.88959921590680779;
    TestInput[8] = 2.2895143999512348;
    TestInput[9] = 1.8725559526661053;
    TestInput[10] = 0.18381391538963335;
    TestInput[11] = 0.97387665546286017;
    TestInput[12] = 1.5158766413100442;
    TestInput[13] = 2.3280036303070153;
    TestInput[14] = 0.71573385287121882;
    TestInput[15] = 0.32368181540087793;*/
	}

  // move just i'th coordinate, where i=0 here refer to first 
  // coordinate
  void customModifySol(double *TestInput, int i) 
  {
    MyMolecule->customModifySol(TestInput, i);
  }

	// to set temperature for calculating derivative of in Likelihood

//	virtual void SetTempForDerivLikelihood(double T)
//	{
//		MyLikelihood->SetTemp(T);
//	}

private:
  int NInput;
	double	   *IDerivative;
	Position   *XDerivative;

	Diffractor *MyDiffractor;
	Likelihood *MyLikelihood;

	Time timer; // to measure time for first HMC publication
};

#endif // !defined(AFX_ZFUNCTION_H__4D84F5B7_572F_11D1_93C2_006097737B41__INCLUDED_)
